package org.eclipse.emf.db.query;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.emf.db.util.DBQueryUtil;
import org.eclipse.emf.extensions.IDBSchema;

class SelectQuery {
    protected List<QueryExpression> select=new ArrayList<QueryExpression>();

    protected FromExpression fromExpression;

    protected QueryExpression where;

    protected QueryExpression orderBy;

    protected boolean orderAsc=true;

    protected QueryExpression groupBy;

    protected QueryExpression having;

    protected Integer limit, offset;

    protected final IDBSchema schema;

    protected SelectQuery(IDBSchema schema) {
        this.schema=schema;
    }

    @Override
    public String toString() {
        String sql=getPreparedStatementSQL();
        for (Object parameter : getParameters())
            sql=StringUtils.replaceOnce(sql, "?", parameter instanceof String ? DBQueryUtil.quote(parameter.toString()) : parameter.toString());
        return sql;
    }

    public Object[] getParameters() {
        if (where == null && having == null)
            return new String[0];
        if (where != null && having == null)
            return where.getParameters();
        if (where == null && having != null)
            return having.getParameters();
        return ArrayUtils.addAll(where.getParameters(), having.getParameters());
    }

    public String getPreparedStatementSQL() {
        StringBuilder builder=new StringBuilder("SELECT "); //$NON-NLS-1$
        boolean first=true;
        for(QueryExpression expr: select) {
            if(!first)
                builder.append(',');

            builder.append(expr.toString(schema));
            first=false;
        }
        builder.append(" FROM "); //$NON-NLS-1$

        fromExpression.appendPrefix(schema, builder);
        fromExpression.appendSuffix(schema, builder);

        if (where != null) {
            builder.append(" WHERE "); //$NON-NLS-1$
            builder.append(where.toString(schema));
        }

        if (orderBy != null) {
            builder.append(" ORDER BY "); //$NON-NLS-1$
            builder.append(orderBy.toString(schema));
            if (!orderAsc)
                builder.append(" DESC"); //$NON-NLS-1$
        }

        if (groupBy!=null) {
            builder.append(" GROUP BY "); //$NON-NLS-1$
            builder.append(groupBy.toString(schema));
        }

        if (having != null) {
            builder.append(" HAVING "); //$NON-NLS-1$
            builder.append(having.toString(schema));
        }

        if (limit != null) {
            builder.append(" LIMIT "); //$NON-NLS-1$
            if (offset != null)
                builder.append(offset).append(',');

            builder.append(limit);
        }

        return builder.toString();
    }
}
